<?php
/**公共方法*/

namespace App\Lib;


use Illuminate\Support\Facades\Route;

class Common {
    /**
     * 将字符串转换编码格式为 UTF-8 编码格式
     */
    public static function getStringUTF8($str, $mode) {
        if (is_numeric($str)) {
            return $str;
        }
        return iconv($mode, "UTF-8", $str);
    }


    /**
     * 获取随机字符串
     */
    public static function getRandChar($length) {
        $str = null;
        $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
        $max = strlen($strPol) - 1;

        for ($i = 0;
             $i < $length;
             $i++) {
            $str .= $strPol[rand(0, $max)];
        }

        return $str;
    }


    /**
     * 重组数组
     * @param $array 需要重组的数组
     */
    public static function fromArrayToModel($array) {
        $m = [];
        foreach ($array as $key => $value) {
            $m[$key] = $value;
        }
        return $m;
    }

    /**
     * 递归key分类
     * @params $data:传入的数组
     * @params $parent_id父类的id
     */
    /*public static function getTree($data, $parent_id = 0) {
        $tree = [];
        foreach ($data as $k => $v) {
            if ($v['parent_id'] == $parent_id) {
                $v['children'] = self::getTree($data, $v['id']);
                $tree[] = $v;
                unset($data[$k]);
            }
        }
        return $tree;
    }*/

    /**
     * 递归key分类
     * @params $data:传入的数组
     * @params $fname:父名称
     * @params $sname:子名称
     * @params $key:主键
     * @params $parent_id父类的id值
     */
    public static function getTree($data, $parent_id = 0,$fname = 'parent_id',$sname='children',$key='id') {
        $tree = [];
        foreach ($data as $k => $v) {
            if ($v[$fname] == $parent_id) {
                if(self::getTree($data, $v[$key],$fname,$sname,$key)) {
                    $v[$sname] = self::getTree($data, $v[$key], $fname, $sname, $key);
                }
                $tree[] = $v;
                unset($data[$k]);
            }
        }
        return $tree;
    }

    /**
     * 加密设置
     * @params $data:加密数据
     * @params $method:加密方法
     * @params $lent:递归层数
     */
    public function set_encry_param($data, $method, $lent) {
        $params = [];
        $params['data'] = $data;
        $params['method'] = $method;
        $params['options'] = [
            "cost" => $lent
        ];
        return $this->get_encrypt($params);
    }

    //加密结果
    private function get_encrypt($params) {
        return password_hash($params['data'], $params['method'], $params['options']);
    }

    /**
     * 验证加密设置
     * @params $data:要验证的数据
     * @params $hash:加密的字符串
     */
    public function set_dencry_param($data, $hash) {
        $params = [];
        $params['data'] = $data;
        $params['hash'] = $hash;
        return $this->get_dencrypt($params);
    }

    //验证加密结果
    private function get_dencrypt($params) {
        return password_verify($params['data'], $params['hash']);
    }

    /**
     * 删除key值
     */
    /**
     * php除数组指定的key值(通过直接重新组装一个数组)
     * @param $data
     * @param $key
     * @return $newArray
     */
    public static function array_remove($data, $delKey) {
        $newArray = array();
        if (is_array($data)) {
            foreach ($data as $key => $value) {
                if ($key !== $delKey) {
                    $newArray[$key] = $value;
                }
            }
        } else {
            $newArray = $data;
        }
        return $newArray;
    }

    /**
     * aes加密
     * @param $data 需要加密的数据
     * @param $method 加密方法 DES-ECB DES-CBC DES-CTR DES-OFB DES-CFB
     * @param $key 加密密钥
     * @param $options 数据格式选项（可选）【选项有：0 OPENSSL_RAW_DATA=1 OPENSSL_ZERO_PADDING=2 OPENSSL_NO_PADDING=3】
     * @param $iv 随机数（可选）
     */
    public function set_encrypt_aes($data, $key, $method = "DES−ECB", $iv = "", $options = 0) {
        $params = [];
        $params["data"] = $data;
        $params["method"] = $method;
        $params["key"] = $key;
        $params["options"] = $options;
        $params["iv"] = $iv;
        $result = $this->get_encrpt_aes($params);
        return $result;
    }

    /**
     * aes加密主体
     */
    private function get_encrpt_aes($params) {
        return openssl_encrypt($params["data"], $params["method"], $params["key"], $params["options"], $params["iv"]);
    }

    /**
     * aes解密
     * @param $data 加密的数据
     * @param $method 加密方法 DES-ECB DES-CBC DES-CTR DES-OFB DES-CFB
     * @param $key 加密密钥
     * @param $options 数据格式选项（可选）【选项有：0 OPENSSL_RAW_DATA=1 OPENSSL_ZERO_PADDING=2 OPENSSL_NO_PADDING=3】
     * @param $iv 随机数（可选）
     */
    public function set_dencrypt_aes($data, $key, $method = "DES−ECB", $iv = "", $options = 0) {
        $params = [];
        $params["data"] = $data;
        $params["method"] = $method;
        $params["key"] = $key;
        $params["options"] = $options;
        $params["iv"] = $iv;
        $result = $this->get_dencrpt_aes($params);
        return $result;
    }

    /**
     * aes加密主体
     */
    private function get_dencrpt_aes($params) {
        return openssl_decrypt($params["data"], $params["method"], $params["key"], $params["options"], $params["iv"]);
    }

    /**
     * 获取时间戳
     * @param $q 传入的标识(0~10)
     * @param $time1 起始时间，格式Y-m-d H:i:s
     * @param $time2 结束时间，格式Y-m-d H:i:s
     */
    public static function get_time($q, $time1, $time2) {
        $now = time();
        $beginTime = 0;
        $endTime = 0;
        switch ($q) {
            case 1://今天
                $beginTime = strtotime(date('Y-m-d 00:00:00', $now));
                $endTime = strtotime(date('Y-m-d 23:59:59', $now));
                break;
            case 2://昨天
                $time = strtotime('-1 day', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', $time));
                $endTime = strtotime(date('Y-m-d 23:59:59', $now));
                break;
            case 3://三天内
                $time = strtotime('-2 day', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', $time));
                $endTime = strtotime(date('Y-m-d 23:59:59', $now));
                break;
            case 4:// 本周
                $time = '1' == date('w') ? strtotime('Monday', $now) : strtotime('last Monday', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', $time));
                $endTime = strtotime(date('Y-m-d 23:59:59', strtotime('Sunday', $now)));
                break;
            case 5:// 上周
                // 本周一
                $thisMonday = '1' == date('w') ? strtotime('Monday', $now) : strtotime('last Monday', $now);
                // 上周一
                $lastMonday = strtotime('-7 days', $thisMonday);
                $beginTime = strtotime(date('Y-m-d 00:00:00', $lastMonday));
                $endTime = strtotime(date('Y-m-d 23:59:59', strtotime('last sunday', $now)));
                break;
            case 6:// 本月
                $beginTime = strtotime(date('Y-m-d 00:00:00', mktime(0, 0, 0, date('m', $now), '1', date('Y', $now))));
                $endTime = strtotime(date('Y-m-d 23:39:59', mktime(0, 0, 0, date('m', $now), date('t', $now), date('Y', $now))));
                break;
            case 7:// 三月内
                $time = strtotime('-2 month', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', mktime(0, 0, 0, date('m', $time), 1, date('Y', $time))));
                $endTime = strtotime(date('Y-m-d 23:39:59', mktime(0, 0, 0, date('m', $now), date('t', $now), date('Y', $now))));
                break;
            case 8:// 半年内
                $time = strtotime('-5 month', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', mktime(0, 0, 0, date('m', $time), 1, date('Y', $time))));
                $endTime = strtotime(date('Y-m-d 23:39:59', mktime(0, 0, 0, date('m', $now), date('t', $now), date('Y', $now))));
                break;
            case 9:// 一年内
                $beginTime = strtotime(date('Y-m-d 00:00:00', mktime(0, 0, 0, 1, 1, date('Y', $now))));
                $endTime = strtotime(date('Y-m-d 23:39:59', mktime(0, 0, 0, 12, 31, date('Y', $now))));
                break;
            case 10:// 三年内
                $time = strtotime('-2 year', $now);
                $beginTime = strtotime(date('Y-m-d 00:00:00', mktime(0, 0, 0, 1, 1, date('Y', $time))));
                $endTime = strtotime(date('Y-m-d 23:39:59', mktime(0, 0, 0, 12, 31, date('Y'))));
                break;
            default:
                $beginTime = strtotime(date($time1));
                $endTime = strtotime(date($time2));
                break;
        }

        return ["begin" => $beginTime, "end" => $endTime];
    }

    /**
     * 是否包含字符串
     * @param $str 主字符串
     * @param $needle 包含的字符串
     */
    public static function checkstr($str, $needle) {
        $tmparray = explode($needle, $str);
        if (count($tmparray) > 1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 数组排序
     * @param $arr 要排序的数组
     * @param $type 根据键，值排序，取值 NO,KEY,VALUE
     * @param $sort 升序或降序，默认升序，取值 ASC,DESC
     */
    public static function num_sort($arr, $type, $sort = "ASC") {
        if (!is_array($arr)) {
            return false;
        }
        //判断类型
        if ($type == "KEY" && $sort == "ASC") {
            ksort($arr);
        } else if ($type == "KEY" && $sort == "DESC") {
            krsort($arr);
        } else if ($type == "VALUE" && $sort == "ASC") {
            asort($arr);
        } else if ($type == "VALUE" && $sort == "DESC") {
            arsort($arr);
        } else if ($type == "NO" && $sort == "ASC") {
            sort($arr);
        } else if ($type == "NO" && $sort == "DESC") {
            rsort($arr);
        } else {
            return false;
        }
        return $arr;
    }

    /**
     * 二位数组排序
     * @param $arr 二维数组
     * @param $shortKey 需要排序的列
     * @param $short 排序方式
     * @param $shortType 排序类型
     */
    public static function multi_array_sort($arr,$shortKey,$short=SORT_DESC,$shortType=SORT_REGULAR)
    {
        foreach ($arr as $key => $data){
            $name[$key] = $data[$shortKey];
        }
        array_multisort($name,$shortType,$short,$arr);
        return $arr;
    }

    /**
     * 创建目录
     * @param $mulu 目录路径
     */
    public static function fileexit($mulu) {
        //判断目录是否存在，不存在则创建
        if (!file_exists($mulu)) {
            //反复回调该方法，创建多层目录
            self::fileexit(dirname($mulu));
            mkdir($mulu);
        }
    }

    /**
     * 密码加密
     * @param $salt 盐
     * @param $password 用户输入的密码
     */
    public function passWord($salt, $password) {
        $result = $this->setPassWord($salt, $password);
        return $result;
    }

    private function setPassWord($salt, $password) {
        $salted = $password . '{' . $salt . '}';

        $algorithm = 'sha256';
        $digest = hash($algorithm, $salted, true);

        $iterations = 5000;
        // "stretch" hash
        for ($i = 1; $i < $iterations; ++$i) {
            $digest = hash($algorithm, $digest . $salted, true);
        }

        return base64_encode($digest);
    }

    /**
     * 生成随机盐
     */
    public function get_salt() {
        $salt = $this->set_salt();
        return $salt;
    }

    private function set_salt() {
        $salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
        return $salt;
    }

    /**
     * laravel中获取路由
     */
    public static function route_uri($name) {
        return app('router')->getRoutes()->getByName($name)->getUri();
    }

    /**
     * 设置全局设置信息
     * @params $key 设置名称
     * @params $value 设置值 类型：array
     */
    public static function set_setting($key,$value){
        return ["name"=>$key,"value"=>$value];
    }

    /**
     * 获取全局设置信息
     * @params $key 设置名称
     */
    public static function get_setting($key){
        return ["name"=>$key];
    }

    /**
     * 获取路由名称
     */
    public static function get_route_name(){
        $routes = Route::getRoutes()->getRoutesByName();
        $array = [];
        foreach ($routes as $route) {
            if (isset($route->action['as']))
                $array[] = $route->action['as'];
        }
        return $array;
    }

    /**
     * 获取一维数组中的所有值
     */
    public static function get_array_value($params){
       return array_values($params);
    }

    /**
     * 处理父级信息
     * @param $list(array) 子级信息
     * @param $data(array) 包含父级，子级的所有信息
     * @param $temp(array) 结果缓存
     */
    public static function father_list($list, $data) {
        $temp = [];
        for ($i = 0; $i < count($list); $i++) {
            $parent_id = array_column($data, 'id');
            $idx = array_search($list[$i]["parent_id"], $parent_id);
            $temp[] = $data[$idx];
            if($idx){
                if ($data[$idx]["parent_id"] > 0) {
                    $idx = array_search($data[$idx]["parent_id"], $parent_id);
                    $temp[] = $data[$idx];
                }
            }
        }
        //排重
        return array_values(array_unique($temp, SORT_REGULAR));
    }

    /**
     * 二维数组根据key去重
     * @param $arr 数组
     * @param $key 键名
     */
    public static function array_unset_tt($arr,$key){
        //建立一个目标数组
        $res = array();
        foreach ($arr as $value) {
            //查看有没有重复项
            if(isset($res[$value[$key]])){
                unset($value[$key]);  //有：销毁
            }else{
                $res[$value[$key]] = $value;
            }
        }
        //重置下标
        $data = [];
        foreach ($res as $v){
            $data[]=$v;
        }
        return $data;
    }
}
